#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define rs resize
#define mp make_pair
#define pi 3.1415926535897932384626433832795
#define sz(a) (int)(a).size()
#define Sort(a) sort((a).begin(), (a).end())
#define Reverse(a) reverse((a).begin(), (a).end())
#define sf scanf
#define pf printf
#define ms(a, x) memset((a), (x), sizeof(a))
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <vvi> vvvi;
typedef vector <vvvi> vvvvi;
typedef vector <bool> vb;
typedef vector <vb> vvb;
typedef vector <vvb> vvvb;
typedef vector <vvvb> vvvvb;
typedef long long ll;
typedef vector <ll> vl;
typedef vector <vl> vvl;
typedef vector <vvl> vvvl;
typedef vector <vvvl> vvvvl;
typedef pair <int, int> ii;
typedef vector <ii> vii;
typedef vector <vii> vvii;
typedef pair <int, ll> il;
typedef vector <il> vil;
typedef vector <vil> vvil;
typedef pair <ll, int> li;
typedef vector <li> vli;
typedef vector <vli> vvli;
typedef set <int> si;
typedef set <li> sli;
typedef set <il> sil;
typedef vector <string> vs;
typedef vector <vs> vvs;
typedef vector <vvs> vvvs;
typedef map <char, int> mci;
typedef pair <ll, ll> pll;

const ll inf = (ll)1e18;

struct edge {
	int to, back;
	ll c, f;
	edge() {}
	edge(int to, int c, int f, int back) : to(to), c(c), f(f), back(back) {}
};

void bfs(int s, vector <vector <edge> > &g, vector <int> &d, ll max_edge) {
	d.assign(sz(g), (int)1e9);
	d[s] = 0;
	queue <int> q;
	q.push(s);
	while (!q.empty()) {
		int v = q.front();
		q.pop();
		for (int i = 0; i < sz(g[v]); ++i) {
			if (g[v][i].c > g[v][i].f && d[g[v][i].to] > d[v] + 1 && g[v][i].c - g[v][i].f >= max_edge) {
				d[g[v][i].to] = d[v] + 1;
				q.push(g[v][i].to);
			}
		}
	}
	return;
}

ll dfs(int v, vector <vector <edge> > &g, vb &u, vi &d, ll flow, int t, ll max_edge) {
	u[v] = 1;
	if (v == t) {
		return flow;
	}
	for (auto &e: g[v]) {
		if (u[e.to] || d[e.to] != d[v] + 1 || e.c == e.f || e.c - e.f < max_edge) {
			continue;
		}
		ll pushed = dfs(e.to, g, u, d, min(flow, e.c - e.f), t, max_edge);
		if (pushed > 0) {
			e.f += pushed;
			g[e.to][e.back].f -= pushed;
			return pushed;
		}
	}
	return 0;
}

ll dinic(int s, int t, vector <vector <edge> > &g) {
	int n = sz(g);
	vi d(n);
	ll flow = 0;
	vb u(n);
	for (ll max_edge = (ll)5e8; max_edge > 0; max_edge /= 2) {
		while (1) {
			bfs(s, g, d, max_edge);
			if (d[t] == (int)1e9) {
				break;
			}
			ll pushed = 1;
			u.assign(n, 0);
			while (pushed = dfs(s, g, u, d, inf, t, max_edge)) {
				u.assign(n, 0);
				flow += pushed;
			}
		}
	}
	return flow;
}

void add_edge(vector <vector <edge> > &g, int v, int to, int c) {
	g[v].pb(edge(to, c, 0, sz(g[to])));
	g[to].pb(edge(v, 0, 0, sz(g[v]) - 1));
	return;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int l = 0, r = 1e8;
	int n, m;
	cin >> n >> m;
	vector <int> a(n + 1);
	int sum = 0;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i];
		sum += a[i];
	}
	vector <vector <edge> > G(n + 2);
	vector <vector <int> > g(n + 1);
	for (int i = 0; i < m; ++i) {
		int x, y;
		cin >> x >> y;
		g[x].pb(y);
	}
	while (l < r) {
		int M = (l + r) / 2;
		//cerr << "Graph" << endl;
		for (int i = 1; i <= n; ++i) {
			add_edge(G, 0, i, a[i]);
			//cerr << 0 << ' ' << i << ' ' << a[i] << endl;
		}
		for (int v = 1; v <= n; ++v) {
			for (int to: g[v]) {
				add_edge(G, v, to, (int)1e9);
				//cerr << v << ' ' << to << ' ' << (int)1e9 << endl;
			}
		}
		for (int v = 1; v <= n; ++v) {
			add_edge(G, v, n + 1, M);
			//cerr << v << ' ' << n + 1 << ' ' << M << endl;
		}
		ll fl = dinic(0, n + 1, G);
		//cerr << fl << endl << endl;
		if (fl == sum) {
			r = M;
		} else {
			l = M + 1;
		}
		for (int i = 0; i < n + 2; ++i) {
			G[i].clear();
		}
	}
	cout << l;
	return 0;
}